/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.consumer.modular.structure.resource.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.listener.CommonDataChangeEventCenter;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.consumer.core.enums.ConsumerDataTypeEnum;
import vip.xiaonuo.consumer.modular.structure.relation.entity.ConsumerRelation;
import vip.xiaonuo.consumer.modular.structure.relation.enums.ConsumerRelationCategoryEnum;
import vip.xiaonuo.consumer.modular.structure.relation.service.ConsumerRelationService;
import vip.xiaonuo.consumer.modular.structure.resource.entity.ConsumerButton;
import vip.xiaonuo.consumer.modular.structure.resource.entity.ConsumerMenu;
import vip.xiaonuo.consumer.modular.structure.resource.enums.ConsumerResourceCategoryEnum;
import vip.xiaonuo.consumer.modular.structure.resource.mapper.ConsumerButtonMapper;
import vip.xiaonuo.consumer.modular.structure.resource.param.button.ConsumerButtonAddParam;
import vip.xiaonuo.consumer.modular.structure.resource.param.button.ConsumerButtonEditParam;
import vip.xiaonuo.consumer.modular.structure.resource.param.button.ConsumerButtonIdParam;
import vip.xiaonuo.consumer.modular.structure.resource.param.button.ConsumerButtonPageParam;
import vip.xiaonuo.consumer.modular.structure.resource.service.ConsumerButtonService;
import vip.xiaonuo.consumer.modular.structure.resource.service.ConsumerMenuService;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 按钮Service接口实现类
 *
 * @author xuyuxiang
 * @date 2022/6/27 14:25
 **/
@Service
public class ConsumerButtonServiceImpl extends ServiceImpl<ConsumerButtonMapper, ConsumerButton> implements ConsumerButtonService {

    @Resource
    private ConsumerRelationService consumerRelationService;

    @Resource
    private ConsumerMenuService consumerMenuService;

    @Override
    public Page<ConsumerButton> page(ConsumerButtonPageParam consumerButtonPageParam) {
        QueryWrapper<ConsumerButton> queryWrapper = new QueryWrapper<ConsumerButton>().checkSqlInjection();
        queryWrapper.lambda().eq(ConsumerButton::getCategory, ConsumerResourceCategoryEnum.BUTTON.getValue());
        if(ObjectUtil.isNotEmpty(consumerButtonPageParam.getParentId())) {
            queryWrapper.lambda().eq(ConsumerButton::getParentId, consumerButtonPageParam.getParentId());
        }
        if(ObjectUtil.isNotEmpty(consumerButtonPageParam.getSearchKey())) {
            queryWrapper.lambda().like(ConsumerButton::getTitle, consumerButtonPageParam.getSearchKey());
        }
        if(ObjectUtil.isAllNotEmpty(consumerButtonPageParam.getSortField(), consumerButtonPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(consumerButtonPageParam.getSortOrder());
            queryWrapper.orderBy(true, consumerButtonPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(consumerButtonPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(ConsumerButton::getSortCode);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ConsumerButtonAddParam consumerButtonAddParam) {
        ConsumerButton consumerButton = BeanUtil.toBean(consumerButtonAddParam, ConsumerButton.class);
        boolean repeatCode = this.count(new LambdaQueryWrapper<ConsumerButton>()
                .eq(ConsumerButton::getCategory, ConsumerResourceCategoryEnum.BUTTON.getValue())
                .eq(ConsumerButton::getCode, consumerButton.getCode())) > 0;
        if(repeatCode) {
            throw new CommonException("存在重复的按钮，编码为：{}", consumerButton.getCode());
        }
        consumerButton.setCategory(ConsumerResourceCategoryEnum.BUTTON.getValue());
        this.save(consumerButton);

        // 发布增加事件
        CommonDataChangeEventCenter.doAddWithData(ConsumerDataTypeEnum.RESOURCE.getValue(), JSONUtil.createArray().put(consumerButton));
    }

    @Override
    public void addForGenButton(String menuId, String className, String functionName,String path) {
        ConsumerMenu consumerMenu = consumerMenuService.queryEntity(menuId);
        String classNameFirstLower = StrUtil.lowerFirst(className);//以下修改添加按钮时，同时添加component，并作为后端权限标识  by Mr.wu 2024-03-24
        CollectionUtil.newArrayList(JSONUtil.createObj().set("title", "新增" + functionName).set("code", classNameFirstLower + "Add").set("sortCode", 1).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "add"),
                JSONUtil.createObj().set("title", "编辑" + functionName).set("code", classNameFirstLower + "Edit").set("sortCode", 2).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "edit"),
                JSONUtil.createObj().set("title", "删除" + functionName).set("code", classNameFirstLower + "Delete").set("sortCode", 3).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "delete"),
                JSONUtil.createObj().set("title", "批量删除").set("code", classNameFirstLower + "BatchDelete").set("sortCode", 4).set("component",StrUtil.removePrefix(path, StrUtil.SLASH) + StrUtil.SLASH + "delete")).forEach(jsonObject -> {
            ConsumerButtonAddParam consumerButtonAddParam = new ConsumerButtonAddParam();
            BeanUtil.copyProperties(jsonObject, consumerButtonAddParam);
            consumerButtonAddParam.setParentId(consumerMenu.getId());
            this.add(consumerButtonAddParam);
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ConsumerButtonEditParam consumerButtonEditParam) {
        ConsumerButton consumerButton = this.queryEntity(consumerButtonEditParam.getId());
        BeanUtil.copyProperties(consumerButtonEditParam, consumerButton);
        boolean repeatCode = this.count(new LambdaQueryWrapper<ConsumerButton>()
                .eq(ConsumerButton::getCategory, ConsumerResourceCategoryEnum.BUTTON.getValue())
                .eq(ConsumerButton::getCode, consumerButton.getCode())
                .ne(ConsumerButton::getId, consumerButtonEditParam.getId())) > 0;
        if(repeatCode) {
            throw new CommonException("存在重复的按钮，编码为：{}", consumerButton.getCode());
        }
        this.updateById(consumerButton);

        // 发布更新事件
        CommonDataChangeEventCenter.doUpdateWithData(ConsumerDataTypeEnum.RESOURCE.getValue(), JSONUtil.createArray().put(consumerButton));
    }

    @Override
    public void delete(List<ConsumerButtonIdParam> consumerButtonIdParamList) {
        List<String> buttonIdList = CollStreamUtil.toList(consumerButtonIdParamList, ConsumerButtonIdParam::getId);
        if(ObjectUtil.isNotEmpty(buttonIdList)) {
            // 获取按钮的父菜单id集合
            List<String> parentMenuIdList = consumerMenuService.list(new LambdaQueryWrapper<ConsumerMenu>().in(ConsumerMenu::getId, buttonIdList)
                    .eq(ConsumerMenu::getCategory, ConsumerResourceCategoryEnum.BUTTON.getValue())).stream().map(ConsumerMenu::getParentId)
                    .collect(Collectors.toList());
            if(ObjectUtil.isNotEmpty(parentMenuIdList)) {
                consumerRelationService.list(new LambdaQueryWrapper<ConsumerRelation>().in(ConsumerRelation::getTargetId, parentMenuIdList)
                        .eq(ConsumerRelation::getCategory, ConsumerRelationCategoryEnum.SYS_ROLE_HAS_RESOURCE.getValue())
                        .isNotNull(ConsumerRelation::getExtJson)).forEach(consumerRelation -> {
                    JSONObject extJsonObject = JSONUtil.parseObj(consumerRelation.getExtJson());
                    List<String> buttonInfoList = extJsonObject.getBeanList("buttonInfo", String.class);
                    if (ObjectUtil.isNotEmpty(buttonInfoList)) {
                        Set<String> intersectionDistinct = CollectionUtil.intersectionDistinct(buttonIdList, buttonInfoList);
                        if(ObjectUtil.isNotEmpty(intersectionDistinct)) {
                            Collection<String> disjunction = CollectionUtil.disjunction(buttonInfoList, intersectionDistinct);
                            extJsonObject.set("buttonInfo", disjunction);
                        }
                    }
                    // 清除对应的角色与资源信息中的【授权的按钮信息】
                    consumerRelationService.update(new LambdaUpdateWrapper<ConsumerRelation>().eq(ConsumerRelation::getId, consumerRelation.getId())
                            .set(ConsumerRelation::getExtJson, JSONUtil.toJsonStr(extJsonObject)));
                });
                // 执行删除
                this.removeByIds(buttonIdList);

                // 发布删除事件
                CommonDataChangeEventCenter.doDeleteWithDataId(ConsumerDataTypeEnum.RESOURCE.getValue(), buttonIdList);
            }
        }
    }

    @Override
    public ConsumerButton detail(ConsumerButtonIdParam consumerButtonIdParam) {
        return this.queryEntity(consumerButtonIdParam.getId());
    }

    @Override
    public ConsumerButton queryEntity(String id) {
        ConsumerButton consumerButton = this.getById(id);
        if(ObjectUtil.isEmpty(consumerButton)) {
            throw new CommonException("按钮不存在，id值为：{}", id);
        }
        return consumerButton;
    }
}
